﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Web.Mvc;

using Steve.UI.Administration.Models;
using AutoMapper;
using System.Diagnostics.CodeAnalysis;
using System.ComponentModel.Composition;

namespace Steve.UI.Administration.Controllers
{
    public class UrlManagementControllerBase : Controller
    {
        [Import]
        public SiteExplorerRepository Repository { get; set; }

        public virtual ActionResult SiteExplorer()
        {
            var sites = Repository.GetSites();

            var model = new SiteExplorerModel();

            model.Sites = sites;

            return View("SiteExplorer", model);
        }

        [ChildActionOrHttpPostAttribute]
        public virtual ActionResult SiteChildUrls(string siteAuthority, string siteName, Uri url)
        {
            DirectoryNode<UrlObject,UrlObjectNodeMetadata> model;
            
            if (!string.IsNullOrEmpty(siteAuthority))
            {
                siteName = Repository.GetSites().NavigateToSite(siteAuthority).SiteName;
            }
            
            
            if (!string.IsNullOrEmpty(siteName))
            {
                model = Repository.GetSiteDirectory(siteName);
            }
            else
            {
                throw new ArgumentException("You must provide either an siteAuthority or a siteName");
            }


            if (url != null)
            {
                model = model.NavigateToDirectory(url);
            }

            return View("SiteChildUrls", model);
        }

        public virtual ActionResult RewriteUrlDetail(Guid? id, Guid? siteUrlId)
        {
            if (id.HasValue && !siteUrlId.HasValue)
            {
                var rewriteUrl = Repository.GetRewriteUrl(id.Value);
                var model = new ExistingUrlRewriteDetailModel();

                Mapper.Map(rewriteUrl, model);

                return View("ExistingRewriteUrlDetail", model);
            }
            else if (siteUrlId.HasValue && !id.HasValue)
            {
                var model = new NewUrlRewriteDetailModel();

                model.SiteUrlId = siteUrlId.Value;
                model.NextRevisionComment = "Initial version";

                return View("NewRewriteUrlDetail", model);
            }
            
            //can only have one or the other id
            throw new InvalidOperationException();
        }

        [HttpPost]
        [ActionName("RewriteUrlDetail")]
        [RouteValueAbsent("id")]
        public virtual ActionResult RewriteUrlDetailPost(NewUrlRewriteDetailModel model)
        {
            if (model == null) throw new ArgumentNullException("model");

            if (!ModelState.IsValid)
            {
                return View("NewRewriteUrlDetail", model);
            }

            var toSave = new RewriteUrl();
            Mapper.Map(model, toSave);

            CheckAndCreateSite(toSave, model.Url);

            Repository.SaveUrlRewrite(toSave);

            return RedirectToAction("SiteExplorer", "UrlManagement");
        }

        [HttpPost]
        [ActionName("RewriteUrlDetail")]
        [RouteValuePresent("id")]
        public virtual ActionResult RewriteUrlDetailPost(ExistingUrlRewriteDetailModel model, Guid id)
        {
            if (model == null) throw new ArgumentNullException("model");

            if (!ModelState.IsValid)
            {
                return View("ExistingRewriteUrlDetail", model);
            }

            var toSave = new RewriteUrl();
            Mapper.Map(model, toSave);
            toSave.Id = id;

            Repository.SaveUrlRewrite(toSave);

            return RedirectToAction("SiteExplorer", "UrlManagement");
        }

        [SuppressMessage("Microsoft.Design", "CA1054:UriParametersShouldNotBeStrings", MessageId = "1#")]
        public virtual ActionResult SiteUrlDetail(Guid? id, string url)
        {
            if (id.HasValue)
            {
                var model = new ExistingSiteUrlDetailModel();
                var siteUrl = Repository.GetSiteUrl(id.Value);
                var rewrites = Repository.GetRewritesForSiteUrl(id.Value);

                model.Rewrites = (from r in rewrites
                                  let uri = r.ToUri(Repository)
                                  select Tuple.Create(uri, r.Id)).ToList();

                Mapper.Map(siteUrl, model);

                return View("ExistingSiteUrlDetail", model);
            }
            else
            {
                var model = new NewSiteUrlDetailModel();
                model.NextRevisionComment = "Initial version";

                if (!string.IsNullOrEmpty(url))
                {
                    model.Url = new Uri(url);
                }

                return View("NewSiteUrlDetail", model);
            }           
        }

        [HttpPost]
        [ActionName("SiteUrlDetail")]
        [RouteValuePresent("id")]
        public virtual ActionResult SiteUrlDetailPost(ExistingSiteUrlDetailModel model, Guid id)
        {
            if (model == null) throw new ArgumentNullException("model");

            if (!ModelState.IsValid)
            {
                return View("ExistingSiteUrlDetail", model);
            }

            var toSave = new SiteUrl();
            Mapper.Map(model, toSave);
            toSave.Id = id;

            Repository.SaveSiteUrl(toSave);

            return RedirectToAction("SiteExplorer", "UrlManagement");
        }

        [HttpPost]
        [ActionName("SiteUrlDetail")]
        [RouteValueAbsent("id")]
        public virtual ActionResult SiteUrlDetailPost(NewSiteUrlDetailModel model)
        {
            if (model == null) throw new ArgumentNullException("model");

            if (!ModelState.IsValid)
            {
                return View("NewSiteUrlDetail", model);
            }

            var toSave = new SiteUrl();
            Mapper.Map(model, toSave);

            CheckAndCreateSite(toSave, model.Url);

            Repository.SaveSiteUrl(toSave);

            return RedirectToAction("SiteExplorer", "UrlManagement");
        }

        [NonAction]
        protected virtual void CheckAndCreateSite(UrlObject toSave, Uri url)
        {
            if (toSave == null) throw new ArgumentNullException("toSave");

            if (toSave.SiteName == null)
            {
                var newSite = CreateSite(url);
                Repository.SaveSite(newSite);
                toSave.SiteName = newSite.SiteName;
            }
        }

        [NonAction]
        protected virtual Site CreateSite(Uri url)
        {
            if (url == null) throw new ArgumentNullException("url");

            var tempSiteName = url.Host;
            var existingSites = Repository.GetSites();
            var counter = 1;

            while (existingSites.Where(s => s.SiteName == tempSiteName).Any())
            {
                tempSiteName = string.Format("{0}{1}", url.Host, counter);
                counter++;
            }

            var newSite = new Site();
            newSite.Authority = url.Authority;
            newSite.IsManagedSite = false;
            newSite.SiteName = tempSiteName;

            return newSite;
        }
    }
}
